package com.hs.android.fortress.ingame;

import net.ubilife.manysense.SubscriberConnection;
import net.ubilife.manysense.VariableType;
import net.ubilife.manysense.adapter.SensorCommand;
import net.ubilife.manysense.adapter.SensorCommand.COMMAND_TYPE;
import net.ubilife.manysense.aggregation.DeviceType;
import net.ubilife.manysense.aggregation.ParcelableException;
import net.ubilife.manysense.aggregation.SensorEvent;
import net.ubilife.manysense.aggregation.SensorEventListener;
import net.ubilife.manysense.aggregation.SensorType;
import net.ubilife.manysense.query.ManySenseSubscriptionQuery;
import net.ubilife.manysense.query.TypeIdentifier;

import com.google.android.gms.maps.model.LatLng;
import com.hs.android.fortress.R;
import com.hs.android.fortress.calculators.AngleHandler;
import com.hs.android.fortress.calculators.AngleStrategy;
import com.hs.android.fortress.model.Bomb;
import com.hs.android.fortress.model.Player;
import com.hs.android.fortress.model.ShootingInfomation;
import com.hs.android.fortress.model.Tank;
import com.hs.android.fortress.net.AsyncNetworking;
import com.hs.android.fortress.net.FormPostCommand;
import com.hs.android.fortress.net.ParamsMaker;
import com.hs.android.fortress.GameApplication;

import android.graphics.Bitmap;
import android.graphics.Typeface;
import android.graphics.drawable.BitmapDrawable;
import android.hardware.SensorManager;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.SoundPool;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.Handler;
import android.os.Message;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.RotateAnimation;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;

public class MenuScreenFragment extends AbstractMenuScreenFragment{

	private static final float A = 0.2f;

//	private SensorManager mSensorManager;

	private final static int AZIMUTH = 0;
	private final static int PITCH = 1;
	private final static int ROLLY = 2;
	
	private float[] mAccData;
	private float[] mMagData;
	private float[] mRotation;
	private float[] mResultData;
	private float[] mResultDataDegree;

	private float[] lowPassDataAcc;
	private float[] lowPassDataMag;

	private ProgressBar mPowerProgBar;
	private ProgressBar mEnergyProgBar;

	private String mUserId;
	private onDirectionChangeListener mDirListener;
	private onPowerPushlListener mPowerListener;

	private TextView mText;
	private CountDownTimer ShootTimer = null;
	private int timeValue = 2;

	private ImageView mImageView;

//	private int mEnergyProgress = 100;
	private boolean mTankTargeted=false;
	private ImageButton mPowerButton;
	private ImageButton mMissailButton1;
	private ImageButton mMissailButton2;

	private int mPowerProgress = 0;
	private boolean mPowerProgressControl = true;
	private boolean mPowerButtonDown = false;
	private ImageButton mModeChageButton;

	private AngleHandler mAngleHandler;
	private AngleStrategy mCurAngleStrategy;
	private float AngleDegree = 0.0f;
	private MediaPlayer mBackgroundSound;
	private SoundPool mPool;
	private int mBombSound, mPowerProgSound;
	private int mMissailBtnClicekedSound;
	private int mDieSound;
	private ShootingInfomation shootInfo;
	private MissailButtonClicked missailButtonClicked;
	private int bombDamage;
	
	private Player mPlayer;
	private Tank mTank;
	private Bomb mCurrentBomb;
	
	private LatLng mLocation;
	// Manysensor
	 private SubscriberConnection connection;
	
	public void setPowerListener(onPowerPushlListener powerListener) {
		mPowerListener = powerListener;
	}

	
	public void setDirListener(onDirectionChangeListener dirListener){
		mDirListener = dirListener;
	}

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		connection = new SubscriberConnection(getActivity());
		connection.registerListener(mManySenseListener);

		mRotation = new float[9];
		mResultData = new float[3];
		mResultDataDegree = new float[3];

		mPlayer = ((GameApplication)getActivity().getApplication()).getPlayer();
		mUserId = mPlayer.getId();
		mTank = mPlayer.getTank();
		mCurrentBomb = mTank.getBomb(0);
		mLocation = mPlayer.getPosition();
		
		mAngleHandler = AngleHandler.getInstance();
		mCurAngleStrategy = mAngleHandler.chageMode();
	}

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {

		View view = inflater.inflate(R.layout.fragment_menuscreen, container,
				false);

		mPowerProgBar = (ProgressBar) view.findViewById(R.id.powerbar);
		mEnergyProgBar = (ProgressBar) view.findViewById(R.id.energybar);
		mText = (TextView) view.findViewById(R.id.mText);
		Typeface face = Typeface.createFromAsset(getActivity().getAssets(),
				"fonts/HANYheadM.ttf");
		mText.setTypeface(face);
		mText.setTextSize(50);
		mImageView = (ImageView) view.findViewById(R.id.imageView2);
		mPowerButton = (ImageButton) view.findViewById(R.id.btn_power);
		mMissailButton1 = (ImageButton) view.findViewById(R.id.btnMissail1);
		mMissailButton1.setOnClickListener(missailClickListener);
		mMissailButton2 = (ImageButton) view.findViewById(R.id.btnMissail2);
		mMissailButton2.setOnClickListener(missailClickListener);
		mModeChageButton = (ImageButton) view.findViewById(R.id.btnModeChanbge);
		mModeChageButton.setOnClickListener(modeChangeListener);
		mBackgroundSound = MediaPlayer.create(this.getActivity(), R.raw.wind);
		mBackgroundSound.setLooping(true);

		int maxStreams = 10;
		mPool = new SoundPool(maxStreams, AudioManager.STREAM_MUSIC, 0);
		mBombSound = mPool.load(this.getActivity(), R.raw.bomb3, 0);
		mPowerProgSound = mPool.load(this.getActivity(), R.raw.pushpower, 0);
		mDieSound = mPool.load(this.getActivity(), R.raw.die, 0);
		mMissailBtnClicekedSound = mPool.load(this.getActivity(), R.raw.missail_click, 0);

		missailButtonClicked = new MissailButtonClicked(mMissailButton1, mMissailButton2, mTank.getTankId());
		shootTimer();

		shootInfo = new ShootingInfomation();

		mPowerButton.setOnTouchListener(new OnTouchListener() {

			@Override
			public boolean onTouch(View v, MotionEvent event) {

				BitmapDrawable drawable = (BitmapDrawable) getActivity()
						.getResources().getDrawable(
								R.drawable.btn_power_touched);
				Bitmap mBtnPowerChangeTouched = drawable.getBitmap();
				mPowerButton.setImageBitmap(mBtnPowerChangeTouched);

				if (timeValue == 0) {

					if (event.getAction() == MotionEvent.ACTION_DOWN) {
						mPowerProgressControl = true;
						mPowerButtonDown = true;
						mPowerProgress = 0;
						new Thread(myTimeThread).start();
					}
					if (event.getAction() == MotionEvent.ACTION_UP) {
						mPool.play(mBombSound, 1, 1, 0, 0, 1);
						mPowerProgressControl = false;
						mPowerButtonDown = false;
						mPowerProgBar.setProgress(0);

						shootInfo.setAngle(AngleDegree);
						shootInfo.setPower(mPowerProgress);
						shootInfo.setDirection(mResultDataDegree[AZIMUTH]);

						mPowerProgBar.setSecondaryProgress(mPowerProgress);
						
						calculateDistance calDis = new calculateDistance(mCurrentBomb.getWeight(), 
								shootInfo.getPower(), shootInfo.getAngle(), shootInfo.getDirection());
						
						calDis.setmLocation(mLocation);
						LatLng explosionLocation=calDis.calLocation();
						
						
						AsyncNetworking.newInstance(null, new FormPostCommand("/gamecontroller/shoot",
								ParamsMaker.makeShootParams(mUserId, mCurrentBomb.getBombId(), explosionLocation.latitude, explosionLocation.longitude)), 
								null).execute();
						mPowerListener.btnPowerClick(explosionLocation, mCurrentBomb, shootInfo.getAngle());

						shootTimer();

					}

				}
				return false;
			}

		});
		return view;
	}
	
	public void setMyLocation(LatLng mPos){
		mLocation = mPos;
	}

	@Override
	public void onResume() {
		super.onResume();

		mBackgroundSound.start();
		mPool.autoResume();

		// ManySensor
		 connection.openConnection();

	}

	@Override
	public void onPause() {
		super.onPause();

		mBackgroundSound.stop();
		mPool.autoPause();

		// ManySensor
		 connection.closeConnection();

	}

	public void powerBtnClicked(View v){

	}
	
	private OnClickListener missailClickListener = new OnClickListener() {
		
		@Override
		public void onClick(View v) {
			switch(v.getId()){
			case R.id.btnMissail1 :
				mPool.play(mMissailBtnClicekedSound,  1,  1, 0, 0, 1);
				mCurrentBomb = mTank.getBomb(0);
				missailButtonClicked.firstMissailClicked(); 
				break;
			case R.id.btnMissail2 :
				mPool.play(mMissailBtnClicekedSound,  1,  1, 0, 0, 1);
				mCurrentBomb = mTank.getBomb(1);
				missailButtonClicked.secondMissailClicked();
				break;
			}
		}
	};

	private float[] doWeightedSmoothing(float[] data, float[] lowPassData) {

		if (lowPassData != null) {
			lowPassData[0] = weightedSmoothing(data[0], lowPassData[0]);
			lowPassData[1] = weightedSmoothing(data[1], lowPassData[1]);
			lowPassData[2] = weightedSmoothing(data[2], lowPassData[2]);

			return lowPassData;		
		} else {
			return data;
		}
	}

	private float weightedSmoothing(float current, float last) {
		return last * (1.0f - A) + current * A;
	}

	private void shootTimer() {

		timeValue = 2;

		ShootTimer = new CountDownTimer(10 * 1000, 1000) {
			public void onTick(long millisUntilFinished) {

				timeValue--;
				mText.setText("" + timeValue);
				if (timeValue == 0) {
					mPowerButton.setImageResource(R.drawable.btn_power);
				}
			}

			@Override
			public void onFinish() {

			}
		};

		ShootTimer.start();
	}

	private void rotateImgAngle(float cuttentValue) {
		Animation an = new RotateAnimation(cuttentValue, cuttentValue, 16, 190);

		an.setDuration(100); // duration in ms
		an.setFillAfter(true); // keep rotation after animation

		mImageView.setAnimation(an);

	}

	private Runnable myTimeThread = new Runnable() {
		@Override
		public void run() {
			
			while (mPowerProgressControl == true) {
				try {
					myHandle.sendMessage(myHandle.obtainMessage());
					Thread.sleep(30);
				} catch (Throwable t) {
				}
			}
		}

		Handler myHandle = new Handler() {
			@Override
			public void handleMessage(Message msg) {
				if (mPowerProgressControl == true) {
					mPowerProgress++;
					mPool.play(mPowerProgSound, 1, 1, 0, 0, 1);
					mPowerProgBar.setProgress(mPowerProgress);
				}

			}
		};
	};

	public int progressValue() {
		return mPowerProgress;
	}

	
	public void setMyEnergyBar(Player player){
		mEnergyProgBar.setMax(player.getTank().getMaxEnergy());
		
		int energy = player.getEnergy();
		if(energy < 0){
			energy = 0;
		}
		mEnergyProgBar.setProgress(energy);
	}

	ImageButton.OnClickListener modeChangeListener = new ImageButton.OnClickListener() {

		@Override
		public void onClick(View v) {
			mPool.play(mMissailBtnClicekedSound,  1,  1, 0, 0, 1);
			mCurAngleStrategy = mAngleHandler.chageMode();
			mModeChageButton
					.setImageResource(mCurAngleStrategy.getBtnImageId());
		}

	};

	
	private SensorEventListener mManySenseListener = new net.ubilife.manysense.aggregation.SensorEventListener() {
		
		@Override
		public void serviceConnectionChanged(boolean connected) {
			if (connected) {
				ManySenseSubscriptionQuery query = new ManySenseSubscriptionQuery();
				query.getTypeIdentifiers().add(
						new TypeIdentifier(DeviceType.PHONE,
								SensorType.ACCELEROMETER));
				query.getTypeIdentifiers().add(
						new TypeIdentifier(DeviceType.PHONE,
								SensorType.MAGNETIC_FIELD));

				query.getCommands().add(
						new SensorCommand(COMMAND_TYPE.SET_UPDATE_INTERVAL,
								new VariableType(150)));

				 connection.addSubscription(query);
			}
		}
		
		@Override
		public void sensorUpdated(SensorEvent event) {
			 if(event.getSensorType().equals(SensorType.ACCELEROMETER)){
			 mAccData = event.getData().getAsFloatArray().clone();
			 }else if(event.getSensorType().equals(SensorType.MAGNETIC_FIELD)){
			 mMagData = event.getData().getAsFloatArray().clone();
			 }
			 
			if (mAccData != null && mMagData != null) {

				lowPassDataAcc = doWeightedSmoothing(mAccData, lowPassDataAcc);
				lowPassDataMag = doWeightedSmoothing(mMagData, lowPassDataMag);

				SensorManager.getRotationMatrix(mRotation, null, lowPassDataAcc,
						lowPassDataMag);
				SensorManager.getOrientation(mRotation, mResultData);
				if (!mPowerButtonDown) {
					mResultData[AZIMUTH] = (float) Math
							.toDegrees((double) mResultData[AZIMUTH]);
					if (mResultData[AZIMUTH] < 0)
						mResultData[AZIMUTH] += 360;
					mResultDataDegree[AZIMUTH] = (mResultData[AZIMUTH] + 90) % 360;

					mResultData[ROLLY] = (float) Math
							.toDegrees((double) mResultData[ROLLY]);
					mResultData[ROLLY] = (float) Math
							.abs((double) mResultData[ROLLY]);
					mResultDataDegree[ROLLY] = mResultData[ROLLY] - 90.0f;
				}

				AngleDegree = mCurAngleStrategy
						.setAngleDegree(mResultDataDegree[ROLLY]);

				rotateImgAngle(AngleDegree);

				if (mDirListener != null) {
					getActivity().runOnUiThread(new Runnable() {
						
						@Override
						public void run() {
							mDirListener.onDirectionChanged(mResultDataDegree[AZIMUTH]);
							
						}
					});
				}

			}
		}
		
		@Override
		public void sensorStopped(net.ubilife.manysense.aggregation.SensorEvent arg0) {
			// TODO Auto-generated method stub
			
		}
		
		@Override
		public void sensorStarted(net.ubilife.manysense.aggregation.SensorEvent arg0) {
			// TODO Auto-generated method stub
			
		}
		
		@Override
		public void sensorException(int arg0, int arg1, ParcelableException arg2) {
			// TODO Auto-generated method stub
			
		}
		
		@Override
		public void sensorError(int arg0, int arg1, ParcelableException arg2) {
			// TODO Auto-generated method stub
			
		}
	};
}
